package com.gitee.cui.security.oio;

import com.gitee.cui.config.SystemConfig;
import com.gitee.cui.ssl.SSLContextHelper;
import com.gitee.cui.util.IOUtil;
import lombok.extern.slf4j.Slf4j;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

/**
 * SSL安全协议实现的阻塞式回显通信
 * @author cuiqingqiang
 * @version 1.0
 * @date 2021/11/5 14:19
 **/
@Slf4j
public class SSLEchoServer {

    static SSLServerSocket serverSocket;

    public static void startServer() {
        try {
            SSLContext context = SSLContextHelper.createServerSSLContext();
            SSLServerSocketFactory factory = context.getServerSocketFactory();
            serverSocket = (SSLServerSocket) factory.createServerSocket(SystemConfig.SOCKET_SERVER_PORT);
            // false:设置单项认证，只需要客户端认证，服务端不需要校验客户端证书信息，true:需要服务端认证客户端证书
            serverSocket.setNeedClientAuth(true);
            // 在握手时，使用服务端模式
            serverSocket.setUseClientMode(false);
            String[] suites = serverSocket.getEnabledCipherSuites();
            serverSocket.setEnabledCipherSuites(suites);
            log.info("SSL OIO ECHO 服务已经启动：{}:{}", SystemConfig.SOCKET_SERVER_IP, SystemConfig.SOCKET_SERVER_PORT);

            while (!Thread.interrupted()) {
                Socket socket = serverSocket.accept();
                log.info("client remote address: {}", socket.getRemoteSocketAddress());
                InputStream inputStream = socket.getInputStream();
                OutputStream outputStream = socket.getOutputStream();
                StringBuffer sb = new StringBuffer();
                byte[] buffer = new byte[1024];
                int length = 0;
                while ((length = inputStream.read(buffer)) != -1) {
                    String msg = new String(buffer, 0, length);
                    log.info("服务端收到：{}", msg);
                    sb.append(msg);
                    if (msg.contains("\r\n")) {
                        break;
                    }
                }
                // 发送消息到客户端
                outputStream.write(sb.toString().getBytes(StandardCharsets.UTF_8));
                outputStream.flush();
                IOUtil.closeQuietly(inputStream);
                IOUtil.closeQuietly(outputStream);
                IOUtil.closeQuietly(socket);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOUtil.closeQuietly(serverSocket);
        }
    }
}
